home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / Apache 1.0 / src / rfc931.c < prev    next >
Text File  |  1995-12-04  |  9KB  |  298 lines

  1.  
  2. /* ====================================================================
  3.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer. 
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in
  14.  *    the documentation and/or other materials provided with the
  15.  *    distribution.
  16.  *
  17.  * 3. All advertising materials mentioning features or use of this
  18.  *    software must display the following acknowledgment:
  19.  *    "This product includes software developed by the Apache Group
  20.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  21.  *
  22.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  23.  *    endorse or promote products derived from this software without
  24.  *    prior written permission.
  25.  *
  26.  * 5. Redistributions of any form whatsoever must retain the following
  27.  *    acknowledgment:
  28.  *    "This product includes software developed by the Apache Group
  29.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  32.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  35.  * IT'S CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  42.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  43.  * ====================================================================
  44.  *
  45.  * This software consists of voluntary contributions made by many
  46.  * individuals on behalf of the Apache Group and was originally based
  47.  * on public domain software written at the National Center for
  48.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  49.  * For more information on the Apache Group and the Apache HTTP server
  50.  * project, please see <http://www.apache.org/>.
  51.  *
  52.  */
  53.  
  54.  
  55. /*
  56.  * rfc931() speaks a common subset of the RFC 931, AUTH, TAP and IDENT
  57.  * protocols. The code queries an RFC 931 etc. compatible daemon on a remote
  58.  * host to look up the owner of a connection. The information should not be
  59.  * used for authentication purposes. This routine intercepts alarm signals.
  60.  * 
  61.  * Diagnostics are reported through syslog(3).
  62.  * 
  63.  * Author: Wietse Venema, Eindhoven University of Technology,
  64.  * The Netherlands.
  65.  */
  66.  
  67. /* Some small additions for Shambhala --- ditch the "sccsid" var if
  68.  * compiling with gcc (it *has* changed), include conf.h for the
  69.  * prototypes it defines on at least one system (SunlOSs) which has
  70.  * them missing from the standard header files, and one minor change
  71.  * below (extra parens around assign "if (foo = bar) ..." to shut up
  72.  * gcc -Wall).
  73.  */
  74.  
  75. #include "conf.h"
  76.  
  77. #ifdef NOTDEF            /* Has changed slightly... */
  78. static char sccsid[] = "@(#) rfc931.c 1.8 93/12/13 22:23:20";
  79. #endif
  80.  
  81. #ifndef _HPUX_SOURCE
  82. #define _HPUX_SOURCE
  83. #endif
  84.  
  85. /* System libraries. */
  86.  
  87. #include <stdio.h>
  88. #ifndef QNX
  89. #include <syslog.h>
  90. #endif
  91. #include <sys/types.h>
  92. #ifndef ULTRIX_BRAIN_DEATH
  93. #include <sys/socket.h>
  94. #endif
  95. #ifdef __bsdi__
  96. #if _BSDI_VERSION > 199312
  97. #include <netinet/in.h>
  98. #endif
  99. #else
  100. #include <netinet/in.h>
  101. #endif
  102. #include <setjmp.h>
  103. #include <signal.h>
  104. #ifndef NEXT
  105. #include <unistd.h>
  106. #endif
  107.  
  108. #ifndef SCO
  109. extern char *strchr();
  110. extern char *inet_ntoa();
  111. #endif
  112.  
  113. /* Local stuff. */
  114.  
  115. /* #include "log_tcp.h" */
  116.  
  117. #define RFC931_TIMEOUT    500
  118. #define    RFC931_PORT    113        /* Semi-well-known port */
  119. #define    ANY_PORT    0        /* Any old port will do */
  120. #define FROM_UNKNOWN  "unknown"
  121.  
  122. int     rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
  123.  
  124. static jmp_buf timebuf;
  125.  
  126. #ifdef QNX
  127.  
  128. /*
  129. Gasp! QNX doesn't support syslog() (out of the box). Replace with output to
  130. stderr. Really, this module should use Apache error logging, but then it would
  131. need considerable hacking.
  132.  
  133. 9 Oct 95
  134. Ben Laurie <ben@algroup.co.uk>
  135. */
  136. #include <assert.h>
  137.  
  138. #define LOG_ERR 0
  139.  
  140. void syslog(int err,const char *str)
  141. {
  142.   char logbuf[200];
  143.   int n=ind(str,'%');
  144.  
  145.   assert(n >= 0);
  146.   memcpy(logbuf,str,n);
  147.   logbuf[n]='\0';
  148.   
  149.   fprintf(stderr,"%ssystem error %d",logbuf,errno);
  150. }
  151.  
  152. #endif /* def QNX */
  153.  
  154. /* fsocket - open stdio stream on top of socket */
  155.  
  156. static FILE *fsocket(domain, type, protocol)
  157. int     domain;
  158. int     type;
  159. int     protocol;
  160. {
  161.     int     s;
  162.     FILE   *fp;
  163.  
  164.     if ((s = socket(domain, type, protocol)) < 0) {
  165.     syslog(LOG_ERR, "socket: %m");
  166.     return (0);
  167.     } else {
  168.     if ((fp = fdopen(s, "r+")) == 0) {
  169.         syslog(LOG_ERR, "fdopen: %m");
  170.         close(s);
  171.     }
  172.     return (fp);
  173.     }
  174. }
  175.  
  176. /* bind_connect - bind both ends of a socket */
  177.  
  178. int     bind_connect(s, local, remote, length)
  179. int     s;
  180. struct sockaddr *local;
  181. struct sockaddr *remote;
  182. int     length;
  183. {
  184.     if (bind(s, local, length) < 0) {
  185.     syslog(LOG_ERR, "bind: %m");
  186.     return (-1);
  187.     } else {
  188.     return (connect(s, remote, length));
  189.     }
  190. }
  191.  
  192. /* timeout - handle timeouts */
  193.  
  194. static void timeout(sig)
  195. int     sig;
  196. {
  197.     longjmp(timebuf, sig);
  198. }
  199.  
  200. /* rfc931 - return remote user name, given socket structures */
  201.  
  202. char   *rfc931(rmt_sin, our_sin)
  203. struct sockaddr_in *rmt_sin;
  204. struct sockaddr_in *our_sin;
  205. {
  206.     unsigned rmt_port;
  207.     unsigned our_port;
  208.     struct sockaddr_in rmt_query_sin;
  209.     struct sockaddr_in our_query_sin;
  210.     static char user[256];        /* XXX */
  211.     char    buffer[512];        /* XXX */
  212.     char   *cp;
  213.     static char *result;    /* XXX */
  214.     FILE   *fp;
  215.  
  216.     result = FROM_UNKNOWN;
  217.     /*
  218.      * Use one unbuffered stdio stream for writing to and for reading from
  219.      * the RFC931 etc. server. This is done because of a bug in the SunOS
  220.      * 4.1.x stdio library. The bug may live in other stdio implementations,
  221.      * too. When we use a single, buffered, bidirectional stdio stream ("r+"
  222.      * or "w+" mode) we read our own output. Such behaviour would make sense
  223.      * with resources that support random-access operations, but not with
  224.      * sockets.
  225.      */
  226.  
  227.     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  228.     setbuf(fp, (char *) 0);
  229.  
  230.     /*
  231.      * Set up a timer so we won't get stuck while waiting for the server.
  232.      */
  233.  
  234.     if (setjmp(timebuf) == 0) {
  235.         signal(SIGALRM, timeout);
  236.         alarm(rfc931_timeout);
  237.  
  238.         /*
  239.          * Bind the local and remote ends of the query socket to the same
  240.          * IP addresses as the connection under investigation. We go
  241.          * through all this trouble because the local or remote system
  242.          * might have more than one network address. The RFC931 etc.
  243.          * client sends only port numbers; the server takes the IP
  244.          * addresses from the query socket.
  245.          */
  246.  
  247.         our_query_sin = *our_sin;
  248.         our_query_sin.sin_port = htons(ANY_PORT);
  249.         rmt_query_sin = *rmt_sin;
  250.         rmt_query_sin.sin_port = htons(RFC931_PORT);
  251.  
  252.         if (bind_connect(fileno(fp),
  253.                  (struct sockaddr *) & our_query_sin,
  254.                  (struct sockaddr *) & rmt_query_sin,
  255.                  sizeof(our_query_sin)) >= 0) {
  256.  
  257.         /*
  258.          * Send query to server. Neglect the risk that a 13-byte
  259.          * write would have to be fragmented by the local system and
  260.          * cause trouble with buggy System V stdio libraries.
  261.          */
  262.  
  263.         fprintf(fp, "%u,%u\r\n",
  264.             ntohs(rmt_sin->sin_port),
  265.             ntohs(our_sin->sin_port));
  266.         fflush(fp);
  267.  
  268.         /*
  269.          * Read response from server. Use fgets()/sscanf() so we can
  270.          * work around System V stdio libraries that incorrectly
  271.          * assume EOF when a read from a socket returns less than
  272.          * requested.
  273.          */
  274.  
  275.         if (fgets(buffer, sizeof(buffer), fp) != 0
  276.             && ferror(fp) == 0 && feof(fp) == 0
  277.             && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  278.                   &rmt_port, &our_port, user) == 3
  279.             && ntohs(rmt_sin->sin_port) == rmt_port
  280.             && ntohs(our_sin->sin_port) == our_port) {
  281.  
  282.             /*
  283.              * Strip trailing carriage return. It is part of the
  284.              * protocol, not part of the data.
  285.              */
  286.  
  287.             if ((cp = strchr(user, '\r')))
  288.             *cp = 0;
  289.             result = user;
  290.         }
  291.         }
  292.         alarm(0);
  293.     }
  294.     fclose(fp);
  295.     }
  296.     return (result);
  297. }
  298.